"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".

Replace this with more appropriate tests for your application.
"""

from django.test import TestCase
from django.test.client import Client
from django.core.urlresolvers import reverse
from Xlib.Xcursorfont import target
from transsys import TranssysProgram, Factor, ExpressionNodeValue, Gene, PromoterElementConstitutive
from trsysmodis import SimGenex, Procedure, TreatmentInstruction

class SimpleTest(TestCase):
    def setUp(self):
        self.client = Client()
    def test_basic_addition(self):
        """
        Tests that 1 + 1 always equals 2.
        """
        self.assertEqual(1 + 1, 2)
    def test_static_page(self):
        """
        Test that all static pages working correctly
        """
        response = self.client.get('/transsysweb/')
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/transsysweb/ts/')
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/transsysweb/sgx/')
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/transsysweb/help')
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/transsysweb/about_us')
        self.assertEqual(response.status_code, 200)

    def test_add_tp_success(self):
        """
        Test that add transsys program function works correctly-Success Scenario
        """
        tp_name = 'testTranssysProgram'
        tp_desc = 'Test Transsys Program'
        #Simulate a get request
        res = self.client.get('/transsysweb/ts/addTranssysProgram')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        res = self.client.post('/transsysweb/ts/addTranssysProgram',
            {'name':tp_name, 'desc':tp_desc})
        #Check that there are no error in creating transsys program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.ts.viewTP', args=[tp_name]))
        #Check that new transsys program is added to the session
        new_tp = self.client.session['ts_programs'][0]['tp']
        self.assertEqual(new_tp.name, tp_name)

    def test_add_tp_failure(self):
        """
        Test that add transsys program function works correctly-Failure Scenario(dupplicated name)
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTranssysProgram'
        tp_desc = 'Test Transsys Program'
        #Create fixture
        tp = TranssysProgram(tp_name)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()
        #Simulate a get request
        res = self.client.get('/transsysweb/ts/addTranssysProgram')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        res = self.client.post('/transsysweb/ts/addTranssysProgram',
            {'name':tp_name, 'desc':tp_desc})
        #Check that the response is 200 and exception is handled
        self.assertEqual(res.status_code, 200)
        self.assertContains(res, "Name of transsys programs must be unique!")
        
    def test_add_factor_success(self):
        """
        Test that add factor function works correctly
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        factor_name = 'factor1'
        decay = "0.1"
        diffusibility = "0"
        
        tp = TranssysProgram(tp_name)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()
        
        #Simulate a post request to add new factor
        response = self.client.post('/transsysweb/ts/'+tp_name+'/factor/add', {'name':factor_name, 'decay':decay, 'diffusibility':diffusibility})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(response, reverse('tsworkbench.views.ts.viewTP', args=[tp_name])+"?with_sgx="+str(with_sgx))
        self.assertEqual(self.client.session['ts_programs'][0]['tp'].factor_list[0].name, factor_name)

    def test_add_factor_failure(self):
        """
        Test that factor won't be added if factor name is dubplicated
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        existing_factor_name = 'factor1'
        existing_decay = ExpressionNodeValue(0.1)
        existing_diffusibility = ExpressionNodeValue(0)
        factor_name = 'factor1'
        decay = "0.1"
        diffusibility = "0"

        tp = TranssysProgram(tp_name)
        factor = Factor(existing_factor_name, existing_decay, existing_diffusibility)
        tp.factor_list.append(factor)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()

        #Simulate a post request to add new factor
        response = self.client.post('/transsysweb/ts/'+tp_name+'/factor/add', {'name':factor_name, 'decay':decay, 'diffusibility':diffusibility})
        #Check that the response is 200 and exception is handled
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Name of factors must be unique!")

    def test_edit_factor(self):
        """
        Test edit factor function
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        existing_factor_name = 'factor1'
        existing_decay = ExpressionNodeValue(0.1)
        existing_diffusibility = ExpressionNodeValue(0)
        factor_name = 'factor2'
        decay = "0.3"
        diffusibility = "1.0"

        tp = TranssysProgram(tp_name)
        factor = Factor(existing_factor_name, existing_decay, existing_diffusibility)
        tp.factor_list.append(factor)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()

        #Simulate a post request to edit new factor
        response = self.client.post('/transsysweb/ts/'+tp_name+'/factor/'+existing_factor_name+'/edit', {'name':factor_name, 'decay':decay, 'diffusibility':diffusibility, 'submit':'submit'})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(response, reverse('tsworkbench.views.ts.viewTP', args=[tp_name])+"?with_sgx="+str(with_sgx))
        self.assertEqual(self.client.session['ts_programs'][0]['tp'].factor_list[0].name, factor_name)
        
    def test_add_gene(self):
        """
        Test that add gene function works correctly
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        factor_name = 'factor1'
        decay = ExpressionNodeValue(0.1)
        diffusibility = ExpressionNodeValue(0)
        gene_name = 'gene1'
        promoter_type = 'constitutive'
        promoter_expr = '1'
        tp = TranssysProgram(tp_name)
        factor = Factor(factor_name, decay, diffusibility)
        tp.factor_list.append(factor)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()
        
        #Simulate a post request to add new gene
        response = self.client.post('/transsysweb/ts/'+tp_name+'/gene/add', {'name':gene_name, 'product':factor_name, 'ptype':[promoter_type], 'pexpr':[promoter_expr], 'pfactor':['undefined'], 'pexpr1':['undefined'], 'pexpr2':['undefined']})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(response, reverse('tsworkbench.views.ts.viewTP', args=[tp_name])+"?with_sgx="+str(with_sgx))
        self.assertEqual(self.client.session['ts_programs'][0]['tp'].gene_list[0].name, gene_name)
        self.assertEqual(self.client.session['ts_programs'][0]['tp'].gene_list[0].promoter[0].expression.value, float(promoter_expr))

    def test_add_gene_failure(self):
        """
        Test that gene won't be added if gene name is dubplicated
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        factor_name = 'factor1'
        decay = ExpressionNodeValue(0.1)
        diffusibility = ExpressionNodeValue(0)
        gene_name = 'gene1'
        promoter_type = 'constitutive'
        promoter_expr = '1'

        factor = Factor(factor_name, decay, diffusibility)
        existing_gene_name = 'gene1'
        existing_product = factor
        existing_promoter_expr = '1'
        gene = Gene(existing_gene_name, existing_product)
        expression_node = ExpressionNodeValue(existing_promoter_expr)
        promoter = PromoterElementConstitutive(expression_node)
        gene.promoter.append(promoter)
        
        tp = TranssysProgram(tp_name)
        
        tp.factor_list.append(factor)
        tp.gene_list.append(gene)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session.save()

        #Simulate a post request to add new gene
        response = self.client.post('/transsysweb/ts/'+tp_name+'/gene/add', {'name':gene_name, 'product':factor_name, 'ptype':[promoter_type], 'pexpr':[promoter_expr], 'pfactor':['undefined'], 'pexpr1':['undefined'], 'pexpr2':['undefined']})
        #Check that the response is 200 and exception is handled
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Name of genes must be unique!")

    def test_run_timesteps(self):
        """
        Test that runtime steps function works correctly
        """
        response = self.client.get('/transsysweb/')
        tp_name = 'testTP'
        with_sgx = 0
        timestep = 100
        fc1=0

        factor_name = 'factor1'
        decay = ExpressionNodeValue(0.1)
        diffusibility = ExpressionNodeValue(0)
        factor = Factor(factor_name, decay, diffusibility)
        gene_name = 'gene1'
        product = factor
        promoter_expr = '1'
        gene = Gene(gene_name, product)
        expression_node = ExpressionNodeValue(promoter_expr)
        promoter = PromoterElementConstitutive(expression_node)
        gene.promoter.append(promoter)
        tp = TranssysProgram(tp_name)
        tp.factor_list.append(factor)
        tp.gene_list.append(gene)
        session = self.client.session
        session['ts_programs'] = []
        session.save()
        session['ts_programs'].append({'tp':tp, })
        session['ts_program'] = {'tp':tp, }
        session.save()

        #Simulate a post request to run timesteps simulation
        response = self.client.post('/transsysweb/ts/'+tp_name+'/runTimestep', {'timestep':timestep, factor_name:fc1})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertEqual(response.status_code, 200)

    def test_upload_transsys_program_success(self):
        #Simulate a get request
        res = self.client.get('/transsysweb/ts/uploadTranssysProgram')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        f = open('testdata/cycler.tra', 'r')
        res = self.client.post('/transsysweb/ts/uploadTranssysProgram',
            {'tp_file':f})
        f.close()
        #Check that there are no error in uploading transsys program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.ts.viewTP', args=['cycler']))
        #Check that new transsys program is added to the session
        new_tp = self.client.session['ts_programs'][0]['tp']
        self.assertEqual(new_tp.name, 'cycler')

    def test_upload_transsys_program_failure(self):
        #Simulate a get request
        res = self.client.get('/transsysweb/ts/uploadTranssysProgram')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        f = open('testdata/error.tra', 'r')
        res = self.client.post('/transsysweb/ts/uploadTranssysProgram',
            {'tp_file':f})
        f.close()
        #Check that the response is 200 and exception is handled
        self.assertEqual(res.status_code, 200)
        self.assertContains(res, "Unable to parse the upload file!")

    def test_edit_transsys_facility(self):
        """
        A integration testcase for test whole edit transsys program facility
        """
        with_sgx = 0
        tp_name = 'testTP'
        tp_desc = 'Test transsys program'
        factor_name = 'factor1'
        decay = "0.5"
        diffusibility = "0.0"
        gene_name = 'gene1'
        promoter_type = 'constitutive'
        promoter_expr = '1'
        timestep = 100
        fc1=0
        #Simulate a post request
        res = self.client.post('/transsysweb/ts/addTranssysProgram',
            {'name':tp_name, 'desc':tp_desc})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.ts.viewTP', args=[tp_name]))
        #Simulate a post request to add new factor
        res = self.client.post('/transsysweb/ts/'+tp_name+'/factor/add',
            {'name':factor_name, 'decay':decay, 'diffusibility':diffusibility})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(res, reverse('tsworkbench.views.ts.viewTP',
            args=[tp_name])+"?with_sgx="+str(with_sgx))
        #Simulate a post request to add new gene
        res = self.client.post('/transsysweb/ts/'+tp_name+'/gene/add',
            {'name':gene_name,
            'product':factor_name,
            'ptype':[promoter_type],
            'pexpr':[promoter_expr],
            'pfactor':['undefined'],
            'pexpr1':['undefined'],
            'pexpr2':['undefined']})
        #Check that there are no error in creating new transsys program and response will redirect to the right page
        self.assertRedirects(res, reverse('tsworkbench.views.ts.viewTP',
            args=[tp_name])+"?with_sgx="+str(with_sgx))
        #Simulate a post request to run timesteps simulation
        res = self.client.post('/transsysweb/ts/'+tp_name+'/runTimestep',
            {'timestep':timestep, factor_name:fc1})
        #Check that there are no error in run simulation tasks
        self.assertEqual(res.status_code, 200)
        #Check the numerical result
        self.assertEqual(self.client.session['ts_program']['simulation_data'].get_factor_expression_list(factor_name)[timestep-1], 2.0)

    def test_add_sgx_success(self):
        """
        Test that add Simgenex program function works correctly-Success Scenario
        """
        sgx_name = 'testSimGenexProgram'
        sgx_desc = 'Test Simgenex Program'
        #Simulate a get request
        res = self.client.get('/transsysweb/sgx/addSgx')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        res = self.client.post('/transsysweb/sgx/addSgx',
            {'name':sgx_name, 'desc':sgx_desc})
        #Check that there are no error in creating transsys program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.sgx.viewSgx', args=[sgx_name]))
        #Check that new transsys program is added to the session
        new_sgx_name = self.client.session['sgx_programs'][0]['name']
        self.assertEqual(new_sgx_name, sgx_name)

    def test_add_sgx_failure(self):
        """
        Test that add SimGenex program function works correctly-Failure Scenario(dupplicated name)
        """
        res = self.client.get('/transsysweb/')
        sgx_name = 'testSimgenexProgram'
        sgx_desc = 'Test SimGenex Program'
        #Create fixture
        sgx = SimGenex([], [], [], [])
        target_tp = []
        sgx_program = {"name":sgx_name, "sgx":sgx, "desc":sgx_desc, "target_tp":target_tp}
        session = self.client.session
        session['sgx_programs'] = []
        session.save()
        session['sgx_programs'].append(sgx_program)
        session.save()
        #Simulate a get request
        res = self.client.get('/transsysweb/sgx/addSgx')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        res = self.client.post('/transsysweb/sgx/addSgx',
            {'name':sgx_name, 'desc':sgx_desc})
        #Check that the response is 200 and exception is handled
        self.assertEqual(res.status_code, 200)
        self.assertContains(res, "Name of SimGenex programs must be unique!")

    def test_add_procedure(self):
        """
        Test that add procedure function works correctly
        """
        res = self.client.get('/transsysweb/')
        sgx_name = 'testSimgenexProgram'
        sgx_desc = 'Test SimGenex Program'
        target_tp = []
        pro_name = 'treatment'
        ins_type = 'treatment'
        ins_factor = 'factor1'
        ins_expr = '1'
        #Create fixture
        sgx = SimGenex([], [], [], [])
        target_tp = []
        sgx_program = {"name":sgx_name, "sgx":sgx, "desc":sgx_desc, "target_tp":target_tp}
        session = self.client.session
        session['sgx_programs'] = []
        session.save()
        session['sgx_programs'].append(sgx_program)
        session.save()
        #Simulate a post request
        res = self.client.post('/transsysweb/sgx/'+sgx_name+'/procedure/add',
            {'name':pro_name, 'instructions.0.itype':ins_type, 'instructions.0.ifactor':ins_factor,'instructions.0.iexpr':ins_expr})
        #Check that there are no error in adding new procedure
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.sgx.viewSgx', args=[sgx_name]))
        #Check that new procedure is added to the simgenex program
        new_procedure = self.client.session['sgx_programs'][0]['sgx'].procedure_defs[0]
        self.assertEqual(new_procedure.procedure_name, pro_name)

    def test_edit_procedure(self):
        """
        Test edit procedure
        """
        """
        Test that add procedure function works correctly
        """
        res = self.client.get('/transsysweb/')
        sgx_name = 'testSimgenexProgram'
        sgx_desc = 'Test SimGenex Program'
        target_tp = []
        pro_name = 'treatment'
        ins_type = 'treatment'
        old_ins_factor = 'factor1'
        old_ins_expr = 1.0
        ins_factor = 'factor2'
        ins_expr = '2'
        #Create fixture
        sgx = SimGenex([], [], [], [])
        target_tp = []
        sgx_program = {"name":sgx_name, "sgx":sgx, "desc":sgx_desc, "target_tp":target_tp}
        #Create a procedure
        new_procedure = Procedure(pro_name, [])
        instruction = TreatmentInstruction(old_ins_factor, old_ins_expr)
        new_procedure.instruction_list.append(instruction)
        #Set instruction to prodedure
        sgx_program["sgx"].procedure_defs.append(new_procedure)
        
        session = self.client.session
        session['sgx_programs'] = []
        session.save()
        session['sgx_programs'].append(sgx_program)
        session.save()
        #Simulate a post request
        res = self.client.post('/transsysweb/sgx/'+sgx_name+'/procedure/'+pro_name+'/edit',
            {'name':pro_name, 'instructions.0.itype':ins_type, 'instructions.0.ifactor':ins_factor,'instructions.0.iexpr':ins_expr})
        #Check that there are no error in adding new procedure
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.sgx.viewSgx', args=[sgx_name]))
        #Check that new procedure is added to the simgenex program
        new_procedure = self.client.session['sgx_programs'][0]['sgx'].procedure_defs[0]
        self.assertEqual(new_procedure.procedure_name, pro_name)
        self.assertEqual(new_procedure.instruction_list[0].factor_name, ins_factor)

    def test_upload_simgenex_program_success(self):
        #Simulate a get request
        res = self.client.get('/transsysweb/sgx/uploadSgx')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        sgx_name = "testUploadSgx"
        f = open('testdata/sgx.sgx', 'r')
        res = self.client.post('/transsysweb/sgx/uploadSgx',
            {'name':sgx_name, 'sgx_file':f})
        f.close()
        #Check that there are no error in uploading simGenex program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.sgx.viewSgx', args=[sgx_name]))
        #Check that new simgenex program is added to the session
        new_sgx_name = self.client.session['sgx_programs'][0]['name']
        new_sgx = self.client.session['sgx_programs'][0]['sgx']
        self.assertEqual(new_sgx_name, sgx_name)
        self.assertIsNotNone(new_sgx)

    def test_upload_simgenex_program_failure(self):
        #Simulate a get request
        res = self.client.get('/transsysweb/sgx/uploadSgx')
        #Check that the response is 200 OK.
        self.assertEqual(res.status_code, 200)
        #Simulate a post request
        f = open('testdata/error.sgx', 'r')
        res = self.client.post('/transsysweb/sgx/uploadSgx',
            {'sgx_file':f})
        f.close()
        #Check that the response is 200 and exception is handled
        self.assertEqual(res.status_code, 200)
        self.assertContains(res, "Uploaded file is invalid!")

    def test_export(self):
        #Create fixture
        #Simulate a post request
        sgx_name = "testUploadSgx"
        f = open('testdata/sgx.sgx', 'r')
        res = self.client.post('/transsysweb/sgx/uploadSgx',
            {'name':sgx_name, 'sgx_file':f})
        f.close()
        #Check that there are no error in uploading simGenex program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.sgx.viewSgx', args=[sgx_name]))
        #Simulate a post request
        f = open('testdata/cycler.tra', 'r')
        res = self.client.post('/transsysweb/ts/uploadTranssysProgram',
            {'tp_file':f})
        f.close()
        #Check that there are no error in uploading transsys program
        #and response will redirect to the right page
        self.assertRedirects(res,
            reverse('tsworkbench.views.ts.viewTP', args=['cycler']))

        #Simulate a get request
        res = self.client.get('/transsysweb/exportWorkspace')
        self.assertEqual(res.status_code, 200)
    def test_import(self):
        res = self.client.get('/transsysweb/importWorkspace')
        self.assertEqual(res.status_code, 200)
        f = open('testdata/TranssysWorkbench.xml', 'r')
        res = self.client.post('/transsysweb/importWorkspace', {'ws_file':f})
        f.close()
        self.assertEqual(res.status_code, 302)
